package com.xueyi.workflow.listener;

import org.flowable.engine.delegate.TaskListener;
import org.flowable.task.service.delegate.DelegateTask;
import org.flowable.identitylink.api.IdentityLink;
import com.xueyi.workflow.service.IWorkflowUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.Map;
import java.util.Date;

/**
 * 自定义任务监听器
 * 处理用户、角色、部门、岗位、表达式到具体用户的映射
 *
 * @author xueyi
 * @date 2024-07-03
 */
@Slf4j
@Component
public class CustomTaskListener implements TaskListener {

    @Autowired
    private IWorkflowUserService workflowUserService;

    @Override
    public void notify(DelegateTask delegateTask) {
        log.info("=== CustomTaskListener被触发 ===");
        log.info("任务ID: {}, 任务名称: {}, 任务定义Key: {}", 
            delegateTask.getId(), delegateTask.getName(), delegateTask.getTaskDefinitionKey());
        log.info("流程实例ID: {}, 流程定义ID: {}", 
            delegateTask.getProcessInstanceId(), delegateTask.getProcessDefinitionId());
        
        // 打印所有流程变量
        log.info("流程变量:");
        delegateTask.getVariables().forEach((key, value) -> {
            log.info("  {}: {}", key, value);
        });

        try {
            Set<Long> allUserIds = new java.util.HashSet<>();

            // 1. 优先从流程变量handlers中获取人员配置
            processHandlersConfig(delegateTask, allUserIds);
            
            // 2. 如果handlers中没有配置，则从BPMN中获取
            if (allUserIds.isEmpty()) {
                log.info("handlers中没有配置人员，尝试从BPMN获取人员配置");
                processBpmnAssignees(delegateTask, allUserIds);
            } else {
                log.info("handlers中已配置人员: {}", allUserIds);
            }

            // 3. 设置任务的人员配置
            if (!allUserIds.isEmpty()) {
                setTaskAssignees(delegateTask, allUserIds);
            } else {
                log.warn("任务 {} 没有找到任何处理人员", delegateTask.getId());
            }

        } catch (Exception e) {
            log.error("CustomTaskListener处理失败", e);
        }
    }

    /**
     * 处理BPMN中定义的候选用户和候选组
     */
    private void processBpmnAssignees(DelegateTask delegateTask, Set<Long> allUserIds) {
        // 获取候选用户（直接指定的用户）
        String candidateUsers = delegateTask.getVariable("candidateUsers") != null ? 
            delegateTask.getVariable("candidateUsers").toString() : null;

        // 获取候选组（角色、部门、岗位、表达式）
        String candidateGroups = delegateTask.getVariable("candidateGroups") != null ? 
            delegateTask.getVariable("candidateGroups").toString() : null;

        // 处理直接指定的候选用户
        if (candidateUsers != null && !candidateUsers.trim().isEmpty()) {
            log.info("处理候选用户: {}", candidateUsers);
            String[] users = candidateUsers.split(",");
            for (String user : users) {
                try {
                    allUserIds.add(Long.valueOf(user.trim()));
                } catch (NumberFormatException e) {
                    log.warn("无效的用户ID: {}", user);
                }
            }
        }

        // 处理候选组（角色、部门、岗位、表达式）
        if (candidateGroups != null && !candidateGroups.trim().isEmpty()) {
            log.info("处理候选组: {}", candidateGroups);
            
            // 解析候选组，格式：role:1,dept:2,post:3,expr:${starter}
            String[] groups = candidateGroups.split(",");
            Set<Long> roleIds = new java.util.HashSet<>();
            Set<Long> deptIds = new java.util.HashSet<>();
            Set<Long> postIds = new java.util.HashSet<>();
            Set<String> expressions = new java.util.HashSet<>();

            for (String group : groups) {
                String[] parts = group.trim().split(":");
                if (parts.length == 2) {
                    String type = parts[0];
                    String value = parts[1];
                    
                    switch (type) {
                        case "role":
                            try {
                                roleIds.add(Long.valueOf(value));
                            } catch (NumberFormatException e) {
                                log.warn("无效的角色ID: {}", value);
                            }
                            break;
                        case "dept":
                            try {
                                deptIds.add(Long.valueOf(value));
                            } catch (NumberFormatException e) {
                                log.warn("无效的部门ID: {}", value);
                            }
                            break;
                        case "post":
                            try {
                                postIds.add(Long.valueOf(value));
                            } catch (NumberFormatException e) {
                                log.warn("无效的岗位ID: {}", value);
                            }
                            break;
                        case "expr":
                            expressions.add(value);
                            break;
                    }
                }
            }

            // 根据角色、部门、岗位查询对应的用户
            Set<Long> groupUserIds = workflowUserService.getUserIdsByGroups(roleIds, deptIds, postIds);
            allUserIds.addAll(groupUserIds);
            log.info("候选组关联的用户: {}", groupUserIds);

            // 处理表达式类型
            if (!expressions.isEmpty()) {
                Set<Long> exprUserIds = workflowUserService.getUserIdsByExpressions(expressions, delegateTask);
                allUserIds.addAll(exprUserIds);
                log.info("表达式关联的用户: {}", exprUserIds);
            }
        }
    }

    /**
     * 处理前端传入的handlers配置
     */
    private void processHandlersConfig(DelegateTask delegateTask, Set<Long> allUserIds) {
        log.info("处理前端传入的handlers配置，任务ID: {}", delegateTask.getId());
        
        // 优先从assigneeConfig中获取handlers配置
        Object assigneeConfigObj = delegateTask.getVariable("assigneeConfig");
        if (assigneeConfigObj instanceof List) {
            List<Map<String, Object>> assigneeConfig = (List<Map<String, Object>>) assigneeConfigObj;
            log.info("从assigneeConfig获取到配置，节点数量: {}", assigneeConfig.size());
            
            for (Map<String, Object> config : assigneeConfig) {
                String nodeId = (String) config.get("id");
                if (nodeId != null && nodeId.equals(delegateTask.getTaskDefinitionKey())) {
                    log.info("找到匹配的节点配置: {}", nodeId);
                    processNodeHandlers(config, allUserIds, delegateTask);
                    
                    // 重要：将handlers设置到流程变量中，供后续方法使用
                    Object handlersObj = config.get("handlers");
                    if (handlersObj != null) {
                        delegateTask.setVariable("handlers", handlersObj);
                        log.info("已将handlers设置到流程变量中: {}", handlersObj);
                    }
                    
                    return;
                }
            }
        }
        
        // 如果没有找到assigneeConfig，尝试从其他流程变量中获取
        String taskDefinitionKey = delegateTask.getTaskDefinitionKey();
        if (taskDefinitionKey != null) {
            // 尝试从节点特定的候选用户变量中获取
            Object candidateUsersObj = delegateTask.getVariable(taskDefinitionKey + "_candidateUsers");
            if (candidateUsersObj instanceof List) {
                List<String> candidateUsers = (List<String>) candidateUsersObj;
                log.info("从节点特定变量获取到候选用户: {}", candidateUsers);
                
                // 转换为handlers格式
                List<Map<String, Object>> handlers = new java.util.ArrayList<>();
                for (String userId : candidateUsers) {
                    Map<String, Object> handler = new java.util.HashMap<>();
                    handler.put("id", userId);
                    handler.put("type", "user");
                    handlers.add(handler);
                }
                
                // 设置handlers变量，供后续处理使用
                delegateTask.setVariable("handlers", handlers);
                
                // 根据节点类型进行不同的处理
                if (isCountersignNode(delegateTask)) {
                    setCountersignTask(delegateTask, candidateUsers);
                } else {
                    setNormalTask(delegateTask, candidateUsers);
                }
                
                return;
            }
        }
        
        log.warn("未找到handlers配置，任务ID: {}, 任务定义Key: {}", 
            delegateTask.getId(), taskDefinitionKey);
    }

    /**
     * 处理节点的人员配置
     */
    private void processNodeHandlers(Map<String, Object> config, Set<Long> allUserIds, DelegateTask delegateTask) {
        try {
            // 处理handlers（处理人员）
            Object handlersObj = config.get("handlers");
            if (handlersObj instanceof List) {
                List<Map<String, Object>> handlers = (List<Map<String, Object>>) handlersObj;
                log.info("找到handlers配置，包含{}个处理人", handlers.size());
                
                for (Map<String, Object> handler : handlers) {
                    log.info("处理handler: {}", handler);
                    Long userId = extractUserId(handler);
                    if (userId != null) {
                        allUserIds.add(userId);
                        log.info("添加处理人员: {}", userId);
                    }
                }
            } else {
                log.warn("handlers不是List类型: {}", handlersObj);
            }
            
            // 处理ccHandlers（抄送人员）
            Object ccHandlersObj = config.get("ccHandlers");
            if (ccHandlersObj instanceof List) {
                List<Map<String, Object>> ccHandlers = (List<Map<String, Object>>) ccHandlersObj;
                log.info("找到ccHandlers配置，包含{}个抄送人", ccHandlers.size());
                
                // 将抄送人员也设置为候选用户，这样他们也能看到任务
                for (Map<String, Object> ccHandler : ccHandlers) {
                    log.info("处理ccHandler: {}", ccHandler);
                    Long userId = extractUserId(ccHandler);
                    if (userId != null) {
                        allUserIds.add(userId);
                        log.info("添加抄送人员: {}", userId);
                    }
                }
            } else {
                log.info("没有找到ccHandlers配置或格式不正确: {}", ccHandlersObj);
            }
            
            // 获取节点的高级配置
            Object advancedObj = config.get("advanced");
            if (advancedObj instanceof Map) {
                Map<String, Object> advanced = (Map<String, Object>) advancedObj;
                delegateTask.setVariable("nodeAdvanced", advanced);
                log.info("设置节点高级配置: {}", advanced);
            }
            
        } catch (Exception e) {
            log.error("处理节点人员配置失败", e);
        }
    }

    /**
     * 统一设置任务人员分配
     */
    private void setTaskAssignees(DelegateTask delegateTask, Set<Long> allUserIds) {
        // 从流程变量中获取handlers配置
        Object handlersObj = delegateTask.getVariable("handlers");
        if (handlersObj == null) {
            log.warn("任务没有handlers配置，任务ID: {}", delegateTask.getId());
            return;
        }
        
        List<Map<String, Object>> handlers = parseHandlers(handlersObj);
        if (handlers.isEmpty()) {
            log.warn("handlers配置为空，任务ID: {}", delegateTask.getId());
            return;
        }
        
        // 提取用户ID列表
        List<String> candidateUsers = new java.util.ArrayList<>();
        for (Map<String, Object> handler : handlers) {
            Long userId = extractUserId(handler);
            if (userId != null) {
                candidateUsers.add(userId.toString());
                allUserIds.add(userId);
            }
        }
        
        if (candidateUsers.isEmpty()) {
            log.warn("没有有效的用户ID，任务ID: {}", delegateTask.getId());
            return;
        }
        
        log.info("从handlers中提取到候选用户: {}", candidateUsers);
        
        // 根据节点类型进行不同的处理
        if (isCountersignNode(delegateTask)) {
            // 会签节点：设置候选用户
            setCountersignTask(delegateTask, candidateUsers);
        } else {
            // 普通节点：根据人数决定分配策略
            setNormalTask(delegateTask, candidateUsers);
        }
        
        // 设置通用流程变量
        delegateTask.setVariable("handlers", handlers);
        delegateTask.setVariable("totalCandidates", candidateUsers.size());
        delegateTask.setVariable("createTime", new Date());
        
        log.info("任务人员分配完成，任务ID: {}, 候选用户数量: {}, 节点类型: {}", 
            delegateTask.getId(), candidateUsers.size(), 
            delegateTask.getVariable("nodeType"));
    }

    /**
     * 设置普通节点任务
     */
    private void setNormalTask(DelegateTask delegateTask, List<String> candidateUsers) {
        if (candidateUsers == null || candidateUsers.isEmpty()) {
            log.warn("普通节点没有配置处理人，任务ID: {}", delegateTask.getId());
            return;
        }
        
        // 设置任务优先级
        String taskDefinitionKey = delegateTask.getTaskDefinitionKey();
        if (taskDefinitionKey != null) {
            String priorityKey = taskDefinitionKey + "_priority";
            Object priorityObj = delegateTask.getVariable(priorityKey);
            if (priorityObj != null) {
                try {
                    Integer priority = Integer.valueOf(priorityObj.toString());
                    delegateTask.setPriority(priority);
                    log.info("设置任务优先级: {} = {}", priorityKey, priority);
                } catch (NumberFormatException e) {
                    log.warn("任务优先级格式错误: {} = {}", priorityKey, priorityObj);
                    // 设置默认优先级
                    delegateTask.setPriority(50);
                }
            } else {
                // 没有配置优先级，设置默认值
                delegateTask.setPriority(50);
                log.info("使用默认任务优先级: 50");
            }
        }
        
        if (candidateUsers.size() == 1) {
            // 只有一个处理人：直接设置为处理人
            String userId = candidateUsers.get(0);
            delegateTask.setAssignee(userId);
            log.info("普通节点单处理人：设置任务处理人为 {}", userId);
            
            // 设置流程变量，标识这是一个已分配的任务
            delegateTask.setVariable("taskStatus", "ASSIGNED");
            delegateTask.setVariable("assignee", userId);
            
        } else {
            // 多个处理人：设置为候选人（需要签收）
            // 重要：清除已设置的 assignee，确保任务不会被直接指派
            delegateTask.setAssignee(null);
            
            for (String userId : candidateUsers) {
                delegateTask.addCandidateUser(userId);
            }
            log.info("普通节点多处理人：设置任务候选用户 {} 人，需要签收", candidateUsers.size());
            
            // 设置流程变量，标识这是一个候选人任务
            delegateTask.setVariable("taskStatus", "CREATED");
            delegateTask.setVariable("candidateUsers", candidateUsers);
            delegateTask.setVariable("candidateCount", candidateUsers.size());
            
            // 不设置assignee，让候选人通过签收来认领任务
        }
        
        // 设置任务类型标识
        delegateTask.setVariable("nodeType", "normal");
        delegateTask.setVariable("isCountersign", false);
    }

    /**
     * 设置会签节点任务
     */
    private void setCountersignTask(DelegateTask delegateTask, List<String> candidateUsers) {
        if (candidateUsers == null || candidateUsers.isEmpty()) {
            log.warn("会签节点没有配置处理人，任务ID: {}", delegateTask.getId());
            return;
        }
        
        // 获取会签配置
        Map<String, Object> countersignConfig = getCountersignConfig(delegateTask);
        
        // 设置候选用户
        for (String userId : candidateUsers) {
            delegateTask.addCandidateUser(userId);
        }
        
        // 设置会签相关变量
        delegateTask.setVariable("countersignType", countersignConfig.get("type"));
        delegateTask.setVariable("completionType", countersignConfig.get("completionType"));
        delegateTask.setVariable("minPass", countersignConfig.get("minPass"));
        delegateTask.setVariable("maxPass", countersignConfig.get("maxPass"));
        
        // 设置任务状态和类型标识
        delegateTask.setVariable("taskStatus", "CREATED");
        delegateTask.setVariable("candidateUsers", candidateUsers);
        delegateTask.setVariable("candidateCount", candidateUsers.size());
        delegateTask.setVariable("nodeType", "countersign");
        delegateTask.setVariable("isCountersign", true);
        
        log.info("会签节点：设置任务候选用户 {} 人，配置: {}", candidateUsers.size(), countersignConfig);
    }

    /**
     * 检查是否为会签节点
     */
    private boolean isCountersignNode(DelegateTask delegateTask) {
        // 从流程变量中获取会签配置
        Object countersignObj = delegateTask.getVariable("nodeAdvanced");
        if (countersignObj instanceof Map) {
            Map<String, Object> advanced = (Map<String, Object>) countersignObj;
            Object countersignObj2 = advanced.get("countersign");
            if (countersignObj2 instanceof Map) {
                Map<String, Object> countersign = (Map<String, Object>) countersignObj2;
                String type = (String) countersign.get("type");
                return type != null && !type.isEmpty();
            }
        }
        return false;
    }

    /**
     * 获取会签配置
     */
    private Map<String, Object> getCountersignConfig(DelegateTask delegateTask) {
        Object countersignObj = delegateTask.getVariable("nodeAdvanced");
        if (countersignObj instanceof Map) {
            Map<String, Object> advanced = (Map<String, Object>) countersignObj;
            Object countersignObj2 = advanced.get("countersign");
            if (countersignObj2 instanceof Map) {
                return (Map<String, Object>) countersignObj2;
            }
        }
        
        // 返回默认配置
        Map<String, Object> defaultConfig = new java.util.HashMap<>();
        defaultConfig.put("type", "");
        defaultConfig.put("completionType", "all");
        defaultConfig.put("minPass", null);
        defaultConfig.put("maxPass", null);
        return defaultConfig;
    }

    /**
     * 解析handlers配置
     */
    @SuppressWarnings("unchecked")
    private List<Map<String, Object>> parseHandlers(Object handlersObj) {
        if (handlersObj instanceof List) {
            return (List<Map<String, Object>>) handlersObj;
        } else {
            log.warn("handlers格式不正确，期望List类型，实际: {}", handlersObj.getClass());
            return new java.util.ArrayList<>();
        }
    }

    /**
     * 提取用户ID
     */
    private Long extractUserId(Map<String, Object> handler) {
        // 支持多种字段名：id, userId
        Object userIdObj = handler.get("id");
        if (userIdObj == null) {
            userIdObj = handler.get("userId");
        }
        
        if (userIdObj != null) {
            try {
                return Long.valueOf(userIdObj.toString());
            } catch (NumberFormatException e) {
                log.warn("无效的用户ID: {}", userIdObj);
            }
        } else {
            log.warn("handler中没有找到有效的用户ID: {}", handler);
        }
        return null;
    }
} 